ログインした際に、メールやSMSに認証コードが送られてくることがありますが、 その値を入力する際のUIをReactNative + typescriptで実装しました。 数値の入力inputが6つあり、入力するたびに次の要素にフォーカスが移動していくやつですね。

こんな感じのUIのイメージです。 ReactNativeで認証コードの入力コンポーネント実装

ソースコードはこんな感じです。

ソースコード

AuthenticationCodeInput.tsx
import React, { createRef, RefObject, useRef, useState } from 'react'
import { StyleSheet, TextInput, View } from 'react-native'

/**
 * const
 */
const inputLength = 6 // 何桁の認証コードか

// 認証コードで入力許可する文字の正規表現
const inputRegExp = new RegExp(/^[0-9]*$/)

/**
 * style
 */
const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    justifyContent: 'center',
  },

  itemContainer: {
    backgroundColor: '#F0F0F0',
    margin: 8,
    borderRadius: 6,
    width: 48,
    height: 50,

    textAlign: 'center',
    fontSize: 37,
  },
})

/**
 * props
 */
interface AuthenticationCodeInputProps {
  onInputEnd: (inputTextArr: string[]) => void
}

/**
 * 認証コード入力
 */
const AuthenticationCodeInput: React.FC<AuthenticationCodeInputProps> = ({ onInputEnd }) => {
  // state
  const [inputArr, setInputArr] = useState<string[]>(() =>
    [...Array(inputLength)].map(() => 0).map((_item) => ''),
  )
  const [currentIndex, setCurrentIndex] = useState(0)

  // ref
  const textInputRefs = useRef<Array<RefObject<TextInput>>>([])
  inputArr.forEach((_, index) => {
    textInputRefs.current[index] = createRef<TextInput>()
  })

  /**
   * 入力値が変更されたとき
   */
  const onChangeTextItem = (_text: string, _index: number) => {
    if (_index >= 0 && _index < inputArr.length) {
      const _arr = inputArr.concat()
      const _currentIndex = _index + 1
      const _lastText = _text.slice(-1) // 末尾の文字のみ取得(一文字になるよう制御)

      // 入力値が入力条件にマッチする場合
      if (inputRegExp.test(_lastText)) {
        _arr[_index] = _lastText

        setInputArr(_arr)

        // indexが範囲内かチェック
        if (_currentIndex < inputArr.length) {
          setCurrentIndex(_currentIndex)

          // フォーカスを次の要素に移動
          textInputRefs.current[_currentIndex].current?.focus()
        }

        // 全て入力済みの場合
        if (_arr.every((_item) => _item != null && _item !== '')) {
          onInputEnd(_arr)
        }
      }
    }
  }

  return (
    <View style={styles.container}>
      {inputArr.map((_item, _itemIndex) => (
        <TextInput
          key={`${_item}_${_itemIndex}`}
          value={_item}
          ref={textInputRefs.current[_itemIndex]}
          style={styles.itemContainer}
          onChangeText={(_text) => {
            onChangeTextItem(_text, _itemIndex)
          }}
          autoFocus={_itemIndex === currentIndex}
        />
      ))}
    </View>
  )
}

export default AuthenticationCodeInput

使い方

Index.tsx
      <AuthenticationCodeInput
        onInputEnd={(_inputTextArr) => {
          console.log('LoginPage onInputEnd()', _inputTextArr)
        }}
      />

onInputEnd メソッドで、入力完了した時の値を配列でうけとることができます。